package top.chengdongqing.mishop.cart

import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import top.chengdongqing.mishop.common.exception.DeletionFailedException
import top.chengdongqing.mishop.common.exception.NotAcceptableException
import top.chengdongqing.mishop.entities.CartItem
import top.chengdongqing.mishop.entities.ProductSKU
import top.chengdongqing.mishop.repositories.CartRepository
import top.chengdongqing.mishop.repositories.ProductRepository
import top.chengdongqing.mishop.repositories.ProductSKURepository

@Service
class CartService(
    private val cartRepository: CartRepository,
    private val productRepository: ProductRepository,
    private val skuRepository: ProductSKURepository
) {

    @Cacheable(value = ["cartItems"], key = "#userId")
    fun findCartItems(userId: Int): List<CartItemDTO> {
        return cartRepository.findAllByUserId(userId).map { CartItemDTO.of(it) }
    }

    @CacheEvict(value = ["cartItems"], key = "#userId")
    fun addToCart(userId: Int, item: CartItemDTO): Int {
        // 查询该商品和sku是否存在
        val product = productRepository.findByIdAndEnabledTrue(item.productId)
            ?: throw NotAcceptableException("该商品不存在")
        val sku = skuRepository.findByIdOrNull(item.skuId)
            ?: throw NotAcceptableException("该SKU不存在")

        // 已添加该商品则仅更新数量
        cartRepository.findBySkuIdAndUserId(item.skuId, userId)?.let {
            it.quantity += item.quantity
            sku.limits?.also { limits ->
                if (it.quantity > limits) {
                    throw NotAcceptableException("商品加入购物车数量超过限购数")
                }
            }
            cartRepository.save(it)
            return it.id
        }

        // 检查库存和加购数量
        checkQuantity(sku, item)

        // 保存该商品到购物车
        val cartItem = CartItem(
            userId = userId,
            product = product,
            sku = sku,
            quantity = item.quantity,
            isChecked = item.isChecked
        )
        cartRepository.save(cartItem)

        return cartItem.id
    }

    @Transactional
    @CacheEvict(value = ["cartItems"], key = "#userId")
    fun modifyCartItems(userId: Int, items: List<CartItemDTO>) {
        val cartItems = items.map {
            // 查询购物车数据
            val cartItem = cartRepository.findBySkuIdAndUserId(it.skuId, userId)
                ?: throw NotAcceptableException("购物车项不存在")
            // 查询sku数据
            val sku = skuRepository.findByIdOrNull(it.skuId) ?: throw NotAcceptableException("SKU 不存在")

            // 检查库存和加购数量
            checkQuantity(sku, it)

            // 返回修改后的购物车项
            cartItem.quantity = it.quantity
            cartItem.isChecked = it.isChecked
            cartItem
        }

        // 批量保存
        cartRepository.saveAll(cartItems)
    }

    @Transactional
    @CacheEvict(value = ["cartItems"], key = "#userId")
    fun removeCartItems(userId: Int, ids: List<Int>) {
        if (cartRepository.deleteAllByIdInAndUserId(ids, userId) == 0) {
            throw DeletionFailedException("删除购物车商品失败")
        }
    }

    @Transactional
    @CacheEvict(value = ["cartItems"], key = "#userId")
    fun syncCart(userId: Int, items: List<CartItemDTO>) {
        items.forEach {
            addToCart(userId, it)
        }
    }
}

private fun checkQuantity(sku: ProductSKU, item: CartItemDTO) {
    // 判断sku库存是否足够
    if (sku.stocks < item.quantity) {
        throw NotAcceptableException("商品库存不足")
    }
    // 判断购买数量是否超出限制
    sku.limits?.also {
        if (item.quantity > it) {
            throw NotAcceptableException("商品加入购物车数量超过限购数")
        }
    }
}